using System;
using Myotragus.Data.Util;
using NHibernate;
using NHibernate.Criterion;

namespace Myotragus.Data.Criteria
{
	public class ReadQueryBuilder : QueryBuilder, IReadQueryBuilder
	{
		public ReadQueryBuilder(ISessionFactoryAdapter sessionFactory)
			: base(sessionFactory)
		{
		}

		public object FindById(Type entityImplementation, object id)
		{
			var session = SessionFactory.OpenSession();
			return session.Get(entityImplementation, id);
		}

		public bool Exists(Type entityImplementation, object id)
		{
			return FindById(entityImplementation, id) != null;
		}

		public ICriteria CreateMatchingCriteria(Type persistentType, object pattern)
		{
			var criteria = CreateCriteria(persistentType);

			foreach (var prop in ReflectionHelper.GetProperties(pattern))
				criteria.Add(Property.ForName(prop.Name).Eq(
					prop.GetValue(pattern, ReflectionHelper.EmptyObjects)));

			return criteria;
		}

		public ICriteria CreateLikeCriteria(Type persistentType, object pattern)
		{
			var criteria = CreateCriteria(persistentType);

			foreach (var prop in ReflectionHelper.GetProperties(pattern))
			{
				var criterionProperty = Property.ForName(prop.Name);
				var value = prop.GetValue(pattern, ReflectionHelper.EmptyObjects);

				criteria.Add(prop.PropertyType == ReflectionHelper.TypeOfString
					? criterionProperty.Like(value.ToString(), MatchMode.Anywhere)
					: criterionProperty.Eq(value));
			}

			return criteria;
		}
	}
}